package com.hyper_yang._03_designpatterns.pattern.creational_patterns;

import java.io.*;

/**
 * @version: 1.0.0
 * @author: sakiko
 * time: 2025/10/8 19:39
 * description: 使用序列化方式破坏单例模式
 */
public class BreakSingletonBySerialize {
    public static void main(String[] args) throws Exception {
//        writeObjectToFile();
        Singleton singleton = readObjectFromFile();
        Singleton singleton2 = readObjectFromFile();
        System.out.println(singleton == singleton2); // 破坏了单例模式 (使用 readSolve()防止反序列化破坏单例模式)
        // note: 原理 ois.readObject ==> readOrdinaryObject ==>  if (...&& desc.hasReadResolveMethod()) Object rep = desc.invokeReadResolve(obj); ...
    }

    // 从文件中读取数据
    public static Singleton readObjectFromFile() throws Exception {
        // 创建对象输入流对象
        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("C:\\Users\\lenovo\\Desktop\\a.txt"));
        // 读取对象
        Singleton instance = (Singleton) ois.readObject();
        // 测试
//        System.out.println(instance);
        // 释放资源
        ois.close();
        return instance;
    }

    // 向文件中写数据
    public static void writeObjectToFile() throws Exception {
        // 获取 Singleton对象
        Singleton instance = Singleton.getInstance();
        // 获取输出流
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("C:\\Users\\lenovo\\Desktop\\a.txt"));
        // 写对象
        oos.writeObject(instance);
        // 释放资源
        oos.close();
    }
}

// java.io.NotSerializableException
class Singleton implements Serializable {
    // 1、私有化构造方法
    private Singleton() {

    }

    // 2、声明本类类型的变量
    private static volatile Singleton instance; // volatile 保证可见性、有序性，预防可能存在指令重排导致的空指针问题

    // 3、提供外部访问
    public static Singleton getInstance() {
        if (instance == null) // 双重检查锁模式
            synchronized (Singleton.class) {
                if (instance == null)
                    instance = new Singleton();
            }
        return instance;
    }

    // 在进行反序列化时，会自动调用该方法，将方法的返回值直接返回
    // 不能随意命名
    public Object readResolve() {
        return Singleton.instance;
    }
}
/*
fixme: 修改了文件，要重新序列化
  java.io.InvalidClassException: ...local class incompatible: stream classdesc serialVersionUID = 5167666417967067719, local class serialVersionUID = 1976504975892324102
todo: 当 JVM完成对象的反序列化后，它会检查这个对象的类是否定义了 readResolve()方法。
  如果定义了，JVM会放弃刚刚通过反序列化创建的那个新对象，转而使用 readResolve()方法的返回值作为最终的结果。
*/